package com.cndym.utils;

import org.apache.commons.httpclient.Cookie;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.HttpMethod;
import org.apache.commons.httpclient.NameValuePair;
import org.apache.commons.httpclient.methods.GetMethod;
import org.apache.commons.httpclient.methods.PostMethod;
import org.apache.commons.httpclient.params.HttpMethodParams;
import org.apache.commons.httpclient.protocol.Protocol;
import org.apache.log4j.Logger;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.HashMap;
import java.util.Map;

public class HttpClientUtils {
    private String url;
    private String encoding = "utf-8";
    private Map<String, String> para;
    private int outTime = 180000;// 3分钟（http连接超时）
    private int reqTime = 150000;// 1分钟（请求超时）
    private HttpClient httpClient;
    private Cookie[] cookie;
    private Logger logger = Logger.getLogger(getClass());


    public HttpClientUtils() {
    }

    public HttpClientUtils(String url) {
        this.url = url;
    }

    public HttpClientUtils(String url, String encoding, Map<String, String> para) {
        this.url = url;
        this.encoding = encoding;
        this.para = para;
    }

    private void init() {
        if (null == httpClient) {
            this.httpClient = new HttpClient();
            this.httpClient.getHttpConnectionManager().getParams().setConnectionTimeout(this.outTime);
            this.httpClient.getState().addCookies(cookie);
        }
    }

    private void init(int outTime) {
        if (null == httpClient) {
            this.httpClient = new HttpClient();
            this.httpClient.getHttpConnectionManager().getParams().setConnectionTimeout(outTime);
            this.httpClient.getState().addCookies(cookie);
        }
    }
    
    @SuppressWarnings("deprecation")
	public HttpClientUtils(String url,String https) {
        this.url = url;
        Protocol myhttps = new Protocol("https", new MySecureProtocolSocketFactory(), 443);
        Protocol.registerProtocol("https", myhttps); //忽略证书有效性检查
        this.httpClient = new HttpClient();
    }

    /**
     * send http request by post method
     * @param outTime
     * @return
     */
    public String httpClientRequest(int outTime, int reqTime) {
    	logger.info("post:" + url);
    	if(outTime >0)
    		init(outTime);
    	else
    		init();
        String value = null;
        if (null == para)
            return value;
        PostMethod postMethod = new PostMethod(url);
        if(reqTime >0)
        	postMethod.getParams().setParameter(HttpMethodParams.SO_TIMEOUT, reqTime);
        else
        	postMethod.getParams().setParameter(HttpMethodParams.SO_TIMEOUT, this.reqTime);
        int len = para.size();
        NameValuePair[] NameValuePairs = new NameValuePair[len];
        int i = 0;
        for (String key : para.keySet()) {
            if (Utils.isNotEmpty(para.get(key))) {
                NameValuePairs[i] = new NameValuePair(key, para.get(key).toString());
                logger.info("[httpclient请求参数]:key=" + key +", value=" + para.get(key).toString());
                i++;
            }
        }
        postMethod.setRequestBody(NameValuePairs);
        postMethod.getParams().setParameter(HttpMethodParams.HTTP_CONTENT_CHARSET, encoding);

        try {
            this.httpClient.executeMethod(postMethod);
            int state = postMethod.getStatusCode();
            if (state == 200) {
                value = this.readInputStream(postMethod.getResponseBodyAsStream());
            } else {
                logger.error("向(" + getUrl() + ")发请求返回state=" + state + "");
            }
        } catch (Exception e) {
            logger.error("发送(" + para + ")失败，原因(" + e.getMessage() + ")");
        }
        postMethod.releaseConnection();
        return value;
    }
    
    @Deprecated
    /**
     * 推荐使用带参数的调用方法  httpClientGet(int outTime, int reqTime)
     * 
     * 自行根据各个业务的具体使用方式， outTime 为建立连接超时时间， reqTime为发送请求超时时间
     * 
     */
    public String httpClientRequest() {
        return this.httpClientRequest(-1, -1);
    }


    public Map<String, String> httpClientRequestD() {
        Map<String, String> map = new HashMap<String, String>();
        map.put("status", "998");
        logger.info("post:" + url);
        init();
        String value = null;
        if (null == para)
            return map;
        PostMethod postMethod = new PostMethod(url);
        postMethod.getParams().setParameter(HttpMethodParams.SO_TIMEOUT, this.reqTime);
        int len = para.size();
        NameValuePair[] NameValuePairs = new NameValuePair[len];
        int i = 0;
        for (String key : para.keySet()) {
            if (Utils.isNotEmpty(para.get(key))) {
                NameValuePairs[i] = new NameValuePair(key, para.get(key).toString());
                i++;
            }
        }
        postMethod.setRequestBody(NameValuePairs);
        postMethod.getParams().setParameter(HttpMethodParams.HTTP_CONTENT_CHARSET, encoding);

        try {
            this.httpClient.executeMethod(postMethod);
            int state = postMethod.getStatusCode();
            map.put("status", state + "");
            if (state == 200) {
                try {
                    value = this.readInputStream(postMethod.getResponseBodyAsStream());
                    map.put("value", value);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            } else {
                logger.error("向(" + getUrl() + ")发请求返回state=" + state + "");
            }
        } catch (IOException e) {
            map.put("status", "999");
            e.printStackTrace();
        }
        postMethod.releaseConnection();
        return map;
    }

    @Deprecated
    /**
     * 推荐使用带参数的调用方法 httpClientGet(int outTime, int reqTime)
     * 自行根据各个业务的具体使用方式， outTime 为建立连接超时时间， reqTime为发送请求超时时间
     * @author chengwei
     */
    public String httpClientGet() {
        return this.httpClientGet(-1, -1);
    }
    
    public String httpClientGet(int outTime, int reqTime) {
        logger.info("get:" + url);
        if(outTime >0)
    		init(outTime);
    	else
    		init();
        HttpMethod httpMethod = new GetMethod(url);
        if(reqTime >0)
        	httpMethod.getParams().setParameter(HttpMethodParams.SO_TIMEOUT, reqTime);
        else
        	httpMethod.getParams().setParameter(HttpMethodParams.SO_TIMEOUT, this.reqTime);
        String value = null;
        try {
            this.httpClient.executeMethod(httpMethod);
            int state = httpMethod.getStatusCode();
            if (state == 200) {
                cookie = httpClient.getState().getCookies();
                value = this.readInputStream(httpMethod.getResponseBodyAsStream());
            } else {
                logger.error("向(" + getUrl() + ")发请求返回state=" + state + "");
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        httpMethod.releaseConnection();
        return value;
    }

    private String readInputStream(InputStream inputStream) throws Exception {
        String reTemp = "";
        String temp = null;
        boolean stop = true;
        BufferedReader buffer = new BufferedReader(new InputStreamReader(inputStream, encoding));
        while (stop) {
            temp = buffer.readLine();
            if (null == temp) {
                stop = false;
            } else {
                reTemp = reTemp + temp;
            }
        }
        return reTemp;
    }

    public String getUrl() {
        return url;
    }

    public void setUrl(String url) {
        this.url = url;
    }

    public Map<String, String> getPara() {
        return para;
    }

    public void setPara(Map<String, String> para) {
        this.para = para;
    }

    public String getEncoding() {
        return encoding;
    }

    public void setEncoding(String encoding) {
        this.encoding = encoding;
    }

    public int getOutTime() {
        return outTime;
    }

    public void setOutTime(int outTime) {
        this.outTime = outTime;
    }

    public int getReqTime() {
        return reqTime;
    }

    public void setReqTime(int reqTime) {
        this.reqTime = reqTime;
    }

    public HttpClient getHttpClient() {
        return httpClient;
    }

    public void setHttpClient(HttpClient httpClient) {
        this.httpClient = httpClient;
    }

    public Cookie[] getCookie() {
        return cookie;
    }

    public void setCookie(Cookie[] cookie) {
        this.cookie = cookie;
    }
}
